Skip to content

[Cases] Add task creation flyout#257864

Closed
michaelolo24 wants to merge 22 commits into
elastic:mainfrom
michaelolo24:cases/tasks-add-task-flyout
Closed

[Cases] Add task creation flyout#257864
michaelolo24 wants to merge 22 commits into
elastic:mainfrom
michaelolo24:cases/tasks-add-task-flyout

Conversation

@michaelolo24
Copy link
Copy Markdown
Contributor

@michaelolo24 michaelolo24 commented Mar 16, 2026

Summary

Adds a flyout for creating tasks from the Tasks tab on the case view page.

Before: The "Add Task" button existed in the component but onAddTask was never wired up, so the button was never rendered.

After: Clicking "Add Task" (in both the empty state and table header) opens a flyout with fields for:

  • Title (required, with inline validation)
  • Description (optional)
  • Status (open / in_progress / completed / cancelled)
  • Priority (low / medium / high / critical)
  • Due date (date picker)

On submit the flyout calls useCreateTask, shows a success/error toast, invalidates the task list query, and closes automatically.

Previous PRs in this series

This PR builds on top of:

  1. PR 1 — Foundation (SO types, feature flag, common types)
  2. PR 2 — CaseTaskService — CRUD, cascade delete, sort order, task summary
  3. PR 3 — CaseTaskTemplateService — CRUD + applyTemplate
  4. PR 4 — Client layer — TasksSubClient + TaskTemplatesSubClient with RBAC
  5. PR 5 — HTTP API routes for tasks and task templates
  6. PR 6 — UI layer — Tasks tab in case view
  7. PR 7 — Task user action builders for activity timeline
  8. PR 8 — OpenAPI docs & telemetry for task management

Files changed

  • add_task_flyout.tsx — new flyout component
  • case_view_tasks.tsx — wires onAddTasksetIsFlyoutOpen(true), renders flyout conditionally
  • translations.ts — adds cancel, field labels, placeholders, and validation strings

Test plan

  • Opening the Tasks tab shows "Add Task" button (empty state) or button in table header
  • Submitting without a title shows an inline error
  • Filling in title + optional fields and submitting creates the task and closes the flyout
  • Success toast appears; task appears in the table
  • Cancel / X closes without creating

🤖 Generated with Claude Code

michaelolo24 and others added 14 commits March 15, 2026 08:39
Adds config schema entry tasks.enabled (default: false) to gate all
task management code behind a feature flag. Updates the mock config
and plugin test fixture to include the new required property.
Adds io-ts runtime schemas and derived TypeScript types for:
- CaseTask (status, priority, assignees, due_date, sort_order,
  custom_fields, task_summary, hierarchy via parent_task_id)
- CaseTaskSummary (denormalized counts + next_due_date for case SO)
- CaseTaskTemplate (scope, relative_due_days, nested subtasks)

Also adds CASE_TASK_SAVED_OBJECT / CASE_TASK_TEMPLATE_SAVED_OBJECT
constants and all task/task_template route URL constants.
Extends UserActionTypes with: create_task, update_task, delete_task,
apply_task_template. Adds io-ts payload schemas for each in
user_action/task/v1.ts and wires them into the main UserAction union.

Server-side BuilderFactory and BuilderParameters are updated to handle
the new types (using NoopUserActionBuilder until PR 4 adds real
renderers). Public-side registers them as UNSUPPORTED_ACTION_TYPES so
the activity timeline skips them gracefully until PR 7 adds UI renders.
…types

Both types use hidden: true, namespaceType: 'multiple-isolated', and
ALERTING_CASES_SAVED_OBJECT_INDEX matching existing Cases SO patterns.

case-task mappings index: case_id, parent_task_id, status, priority,
due_date, assignees.uid, owner, sort_order, created_at.
A parent-case reference is stored in the SO references array via
buildCaseTaskCaseReference().

Both types are gated behind config.tasks.enabled and registered at
modelVersion 1 to establish the migration version chain.
Adds a denormalized task_summary object to the cases SavedObject via
modelVersion 10. The field stores per-status task counts and the
earliest uncompleted due date, avoiding N+1 queries on case list views.

The field is optional/nullable so existing cases are unaffected.
CasePersistedAttributes is updated to reflect the new field.
…rder, task summary sync

Implements the CaseTaskService class covering:
- createTask / bulkCreateTasks with gap-based sort_order (1000 gaps)
- getTask / getTasksByCase / findTasks / getMyTasks with KQL filters
- updateTask with status-transition timestamps (started_at, completed_at)
- bulkUpdateTasks / bulkUpdateTasks
- deleteTask / bulkDeleteTasks with BFS cascade descent deletion
- reorderTasks with 1000-gap sort_order recomputation
- validateDepth (max 2 levels deep) and syncTaskSummary (denormalized on case SO)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements CaseTaskTemplateService:
- createTemplate / getTemplate / findTemplates / updateTemplate / deleteTemplate
- Instance-level 60s TTL cache for template definitions (avoids repeated SO lookups)
- applyTemplate: resolves template, bulk-creates root tasks, then bulk-creates subtasks
  with correct parent_task_id references and relative_due_days → due_date computation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…with RBAC

Adds CasesClient sub-clients for the task management system:
- TasksSubClient: create, get, find, update, delete, reorder, getMyTasks, applyTemplate
- TaskTemplatesSubClient: create, get, find, update, delete
- RBAC: ensureAuthorized / getAuthorizationFilter wired to existing CasesSupportedOperations
- User actions created for create/update/delete/applyTemplate operations (NoopBuilder until PR 7)
- New ReadOperations/WriteOperations enum entries for all task operations
- Factory wires CaseTaskService + CaseTaskTemplateService into CasesServices
- Mock factory updated for existing tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds internal HTTP routes for the task management feature, all gated
behind config.tasks.enabled feature flag.

Task routes (POST/GET/PATCH/DELETE /api/cases/{case_id}/tasks):
- post_task_route: create a task for a case
- get_task_route: retrieve a task by ID
- find_tasks_route: GET /api/cases/tasks/_find with filters
- patch_task_route: partial update a task
- delete_task_route: delete a task
- reorder_tasks_route: PUT _reorder to set sort_order
- get_my_tasks_route: GET /api/cases/tasks/_my for current user
- apply_template_route: POST _apply_template to bulk-create from template

Task template routes (CRUD /api/cases/task_templates):
- post_task_template_route
- get_task_template_route
- find_task_templates_route
- patch_task_template_route
- delete_task_template_route

Both sets are wired in via getTaskRoutes(config) and
getTaskTemplateRoutes(config) spread into getInternalRoutes().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a Tasks tab to the case view page with task list/CRUD UI:

- `CASE_VIEW_PAGE_TABS.TASKS = 'tasks'` added to the enum
- URL helpers for task endpoints added to `common/api/helpers.ts`
- Task API functions added to `containers/api.ts`:
  getCaseTasks, createTask, updateTask, deleteTask, reorderTasks, applyTaskTemplate
- Query/mutation hooks:
  useGetTasks, useCreateTask, useUpdateTask, useDeleteTask
- React components in `components/tasks/`:
  - `TasksTable` — table with status badge cycling, delete action, empty state
  - `CaseViewTasks` — tab-level wrapper that fetches and renders tasks
- `TASKS_TAB` translation string added to case_view/translations.ts
- `CaseViewTabs` now includes a Tasks tab
- `CaseViewPage` renders `<CaseViewTasks>` when Tasks tab is active

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Promotes task-related user action types from UNSUPPORTED to the
activity timeline by adding proper UserActionBuilder implementations.

- Removes create_task, update_task, delete_task, apply_task_template
  from UNSUPPORTED_ACTION_TYPES (now only delete_case remains there)
- Creates tasks.tsx with four UserActionBuilder factories:
  - createCreateTaskUserActionBuilder — "created task 'X'"
  - createUpdateTaskUserActionBuilder — "updated task 'X'"
  - createDeleteTaskUserActionBuilder — "deleted task 'X'"
  - createApplyTaskTemplateUserActionBuilder — "applied a task template and created N task(s)"
- Registers all four builders in builderMap (builder.tsx)
- Adds CREATED_TASK, UPDATED_TASK, DELETED_TASK, APPLIED_TASK_TEMPLATE
  translation functions to translations.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The SavedObjects management API requires importableAndExportable to be
true when visibleInManagement is specified. Updated both cases-tasks
and cases-task-templates SO type definitions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds tasks and task templates to the Cases telemetry schema:
- New CasesTelemetry.tasks field tracking total task count by status and template count
- New getTasksTelemetryData() query in server/telemetry/queries/tasks.ts
- Updated schema.ts and collect_telemetry_data.ts to include tasks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds an AddTaskFlyout component that lets users create tasks directly
from the Tasks tab on the case view:
- Title (required), description, status, priority, and due date fields
- Inline validation for the required title field
- Wires the existing onAddTask callback in CaseViewTasks to open/close
  the flyout; Add Task button now visible in both empty and populated states

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@elasticmachine
Copy link
Copy Markdown
Contributor

elasticmachine commented Mar 16, 2026

🤖 Jobs for this PR can be triggered through checkboxes. 🚧

ℹ️ To trigger the CI, please tick the checkbox below 👇

  • Click to trigger kibana-pull-request for this PR!
  • Click to trigger kibana-deploy-project-from-pr for this PR!
  • Click to trigger kibana-deploy-cloud-from-pr for this PR!
  • Click to trigger kibana-entity-store-performance-from-pr for this PR!
  • Click to trigger kibana-storybooks-from-pr for this PR!

michaelolo24 and others added 8 commits March 16, 2026 05:25
…enable feature by default

Three fixes for the slow/broken tasks tab initial load:

1. Add GET /api/cases/{case_id}/tasks route (get_case_tasks_route.ts).
   The route was missing — only POST existed for that URL, causing the
   UI's getCaseTasks() fetch to receive a 404/405.

2. Set retry: false and staleTime: 30s in useGetTasks. React Query's
   default of 3 retries with exponential backoff turned the 404 into
   ~7 seconds of apparent loading. staleTime avoids unnecessary
   refetches when switching tabs.

3. Change tasks.enabled default to true so the cases-tasks and
   cases-task-templates saved object types are registered automatically,
   fixing the 'Unsupported saved object type: cases-tasks' error on
   task creation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ode paths

Three places could still throw this error even after the default change:

1. getSavedObjectsTypes (common/utils/saved_object_types.ts): task SO
   types were never included, so internal SO repositories created for
   telemetry and other internal operations could not access them.
   Now includes CASE_TASK_SAVED_OBJECT and CASE_TASK_TEMPLATE_SAVED_OBJECT
   when tasks.enabled !== false.

2. createCasesTelemetry (server/telemetry/index.ts): the internal repo
   was built without tasksConfig, so even with tasks enabled the repo
   lacked access. Now threads tasksConfig through from the plugin.

3. collectTelemetryData (server/telemetry/collect_telemetry_data.ts):
   getTasksTelemetryData was called unconditionally — if tasks was
   disabled the SO types were unregistered and the whole telemetry
   collection returned {}. Now skipped when tasksEnabled is false.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds four features to the Tasks UI and backing data model:

Assignees
- New TaskAssigneesField component using useSuggestUserProfiles +
  EuiComboBox with avatar rendering and "Assign yourself" shortcut
- Assignee avatars shown in the table (first 3 + overflow count)

Edit tasks
- New EditTaskFlyout pre-populated from the existing CaseTask
- Shared TaskFormFields component used by both Add and Edit flyouts

Completion notes
- completion_notes optional field added to CaseTaskAttributesRt,
  SO mapping, service args, client params, and HTTP route schemas
- Shown as a textarea in the form only when status = 'completed'

Sub-tasks
- Add sub-task button per row opens AddTaskFlyout with parentTaskId set
- TasksTable builds a flat tree with depth metadata from parent_task_id
  relationships; rows render with indentation and expand/collapse toggle
- Parent tasks are expanded by default

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lates to settings

- Fix task_assignees_field.tsx: add useIsUserTyping hook, pass onDebounce to
  useSuggestUserProfiles, include isUserTyping in isLoading — matches the
  pattern used by case_form_fields/assignees.tsx to prevent infinite spinner
- Fix tasks_table.tsx: replace EuiButtonIcon with EuiButtonEmpty in action
  column so edit/add subtask/delete buttons show icon + text label
- Add task templates section to configure_cases settings page:
  - API functions (findTaskTemplates, createTaskTemplate, updateTaskTemplate,
    deleteTaskTemplate) + query/mutation keys in constants.ts
  - React Query hooks: useGetTaskTemplates, useCreateTaskTemplate,
    useUpdateTaskTemplate, useDeleteTaskTemplate
  - TaskTemplates list component with EuiBasicTable + add/edit/delete
  - TaskTemplateFlyout with name/description/scope fields and dynamic
    tasks list (title/description/priority/relative_due_days per task)
  - Wired into configure_cases/index.tsx below observable types section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rewrote TaskAssigneesField to be an exact mirror of AssigneesComponent
from case_form_fields/assignees.tsx. Key fixes:
- Add useAvailableCasesOwners fallback when context owners array is empty —
  previously passing owners:[] to the suggest API caused unexpected behavior
- Use bringCurrentUserToFrontAndSort for consistent option ordering
- Use isFetching (not isLoading) from useBulkGetUserProfiles, matching ref
- Add isDisabled state computed the same way as the reference component
- Use exact same userProfileToComboBoxOption shape as reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CaseViewTasks was missing CaseViewTabs — every other tab content component
(Activity, Attachments, SimilarCases) renders CaseViewTabs at its top so the
navigation persists. Added CaseViewTabs with activeTab=TASKS to CaseViewTasks
and updated CaseViewPage to pass caseData + searchTerm instead of just caseId.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Checklist visual:
- Add EuiCheckbox to the title column of the tasks table; checked = completed,
  unchecked = open. Toggling the checkbox calls updateTask directly so there
  is no round-trip through the status-cycle badge
- Completed task titles render with line-through + subdued colour so the
  done/not-done state is immediately scannable at a glance
- Status badge remains for in_progress / cancelled granularity

Apply template from cases UI:
- useApplyTaskTemplate hook wraps the existing applyTaskTemplate API call and
  invalidates the task list query on success
- ApplyTemplateModal: EuiModal with EuiSelectable list of templates (shows
  task count per template); confirm button calls applyTemplate then closes
- ApplyTemplateModal shown from CaseViewTasks; "Apply template" button added
  to the TasksTable toolbar and empty-state actions so it is reachable in
  both the populated and empty list states

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add standalone /task-settings page with task statuses and task templates
- Add kanban board view for tasks with drag-and-drop between status columns
- Add task reordering within and across columns
- Fix task status toggling not persisting (ConfigurationPartialAttributesRt missing taskStatuses)
- Fix missing built-in statuses in task form after any custom status is saved
- Fix task create/update API rejecting custom status keys (was validating literal union)
- Handle orphaned task statuses: tasks with deleted statuses show as "Unassigned" / "No status"
- Make column visibility toggles in board view use EuiSwitch with improved spacing
- Wire up task card checkboxes in board view to toggle done/open

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@michaelolo24 michaelolo24 added ci:cloud-deploy Create or update a Cloud deployment ci:cloud-persist-deployment Persist cloud deployment indefinitely Team:Cases Security Solution Cases team poc labels Mar 16, 2026
@kibanamachine
Copy link
Copy Markdown
Contributor

Cloud deployment initiated, see credentials at: https://buildkite.com/elastic/kibana-deploy-cloud-from-pr/builds/844

@michaelolo24 michaelolo24 removed ci:cloud-deploy Create or update a Cloud deployment ci:cloud-persist-deployment Persist cloud deployment indefinitely labels May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

poc Team:Cases Security Solution Cases team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants